package com.example.moudlelibrary.tools;

import com.example.moudlelibrary.dao.ModelingScenarioTemp.FileInfo;
import com.example.moudlelibrary.dao.ModelingScenarioTemp.FileType;
import com.example.moudlelibrary.dao.ModelingScenarioTemp.IoUtil;
import org.apache.commons.io.FileUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * Created by HeYuanqing on 2023/09/05  10:02
 **/
public class FileOperator {
    /**
     * @param folder
     * @return: java.lang.String
     * @Description: 返回文件夹下的所有文件名称，以‘，’分割
     * @Author: HeYuanqing
     * @Date: 2023/9/5 14:41
     */
    public static String listFiles(File folder) {
        // 获取文件夹中的所有文件和子文件夹
        File[] files = folder.listFiles();
        String fileName = "";
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    // 如果是文件夹，递归调用listFiles方法
                    listFiles(file);
                } else {
                    // 如果是文件，打印文件名
                    fileName += file.getName() + ",";

                }
            }
        }
        return fileName;
    }

    /**
     * @param fileNames   需要压缩的文件列表
     * @param zipFilePath 文件压缩包路径
     * @return: boolean
     * @Description: 将文件压缩为压缩包
     * @Author: HeYuanqing
     * @Date: 2023/9/5 14:54
     */
    public static boolean FileToZip(String[] fileNames, String zipFilePath) {
        try {
            // 创建一个输出流，用于写入ZIP文件
            FileOutputStream fos = new FileOutputStream(zipFilePath);
            ZipOutputStream zipOut = new ZipOutputStream(fos);

            for (String filePath : fileNames) {
                // 打开要添加到ZIP文件的文件
                FileInputStream fis = new FileInputStream(filePath);
                // 创建ZIP条目，指定文件名
                ZipEntry zipEntry = new ZipEntry(new File(filePath).getName());
                zipOut.putNextEntry(zipEntry);

                // 将文件内容写入ZIP文件
                byte[] buffer = new byte[1024];
                int length;
                while ((length = fis.read(buffer)) > 0) {
                    zipOut.write(buffer, 0, length);
                }

                // 关闭当前ZIP条目
                zipOut.closeEntry();
                fis.close();
            }

            // 关闭ZIP输出流
            zipOut.close();

            System.out.println("ZIP文件已创建成功：" + zipFilePath);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

    /**
     * @param path: 文件路径
     * @return boolean 文件存在返回true反之false
     * @description 判断文件是否存在
     * @author HYQ
     * @date 2021/8/13 19:37
     */
    public static boolean IsFielExists(String path) {
        File file = new File(path);
        if (file.exists()) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * @param filePaths 需要删除的文件地址
     * @return: void
     * @Description: 根据文件地址删除文件
     * @Author: HeYuanqing
     * @Date: 2023/9/5 15:54
     */
    public static void DeleteFiles(String[] filePaths) {
        for (String filePath : filePaths) {
            File file = new File(filePath);

            if (file.exists()) {
                if (file.delete()) {
                    System.out.println("成功删除文件：" + filePath);
                } else {
                    System.out.println("无法删除文件：" + filePath);
                }
            } else {
                System.out.println("文件不存在：" + filePath);
            }
        }
    }

    /**
     * @param content: 写入的内容
     * @param path:    文件路径
     * @return void
     * @description 写入文件
     * @author HYQ
     * @date 2021/8/11 21:35
     */
    public static void WriteTXTFile(String content, String path) {
        File file = new File(path);
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            fileOutputStream.write(content.getBytes());
            fileOutputStream.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
//        System.out.println("文件写入成功！");
    }

    /**
     * @param path: 文件路径
     * @return String： 返回文件内容
     * @description 读取文件
     * @author HYQ
     * @date 2021/8/13 19:35
     */
    public static String ReadTXTFile(String path) throws Exception {
        FileInputStream fileInputStream = new FileInputStream(path);
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
        String line;
        String content = "";

        while ((line = bufferedReader.readLine()) != null) {
            content += line + "\n";
        }
        fileInputStream.close();
        System.out.println("******文件: " + path + " 读取成功！******");
        return content;
    }

    /**
     * @param filePath txt文件地址
     * @return: java.lang.String
     * @Description: 读取本地txt文件
     * @Author: HeYuanqing
     * @Date: 2023/11/20 20:13
     */
    public static String readTxtFile(String filePath) {
        StringBuilder sb = new StringBuilder();
        try {
            File file = new File(filePath);
            FileReader fileReader = new FileReader(file);
            BufferedReader bufferedReader = new BufferedReader(fileReader);
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                sb.append(line);
                sb.append(System.lineSeparator());
            }
            fileReader.close();
            bufferedReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }
    /**
     * @param dirPath 文件夹名称
     * @return: java.util.Map<java.lang.String, java.lang.Object>
     * @Description: 获取某个目录下的资源树
     * @Author: HeYuanqing
     * @Date: 2023/11/13 14:30
     */
    public static Map<String, Object> readFiles(String dirPath) {

        Map fileAndDirMap = new HashMap(); // 存储目录信息

        // 建立当前目录中文件的File对象
        File curfile = new File(dirPath);
        String foldName = curfile.getName();
        fileAndDirMap.put("name", foldName);
        // 取得代表目录中所有文件的File对象数组
        File[] listFiles = curfile.listFiles();
        if (listFiles != null) {
            List<String> files = new ArrayList<>(); // 存储文件夹下的文件信息
            for (File file : listFiles) {
                if (file.isDirectory()) {
                    fileAndDirMap.put("fold", readFiles(file.getPath()));
                } else {
                    files.add(file.getName());
                }
            }
            fileAndDirMap.put("file", files);
        }
        // 遍历file数组
        return fileAndDirMap;
    }

    /**
     * 用户文件管理
     */
    /**
     * @param fileInfo   文件信息
     * @param isFile     是否获得文件
     * @param isChildren 是否获得子集
     * @return: java.util.List<com.hyq.ghfsystem.util.FileInfo>
     * @Description: 获取文件目录树
     * @Author: HeYuanqing
     * @Date: 2022/11/21 21:17
     */

    public static List<FileInfo> getFileDirectoryTree(FileInfo fileInfo, Boolean isFile, Boolean isChildren) throws FileNotFoundException {
        List<FileInfo> tree = new ArrayList<>();
        //获取根路径配置
        File file = new File(fileInfo.getFilePath());
        if (!file.exists()) {
            throw new FileNotFoundException("文件不存在");
        }

        if (file.isFile()) {
            tree.add(getFileInfo(file, fileInfo));
        } else {
            fileInfo.setFileType(FileType.folder);
            File[] files = file.listFiles();
            for (File f : files) {
                if (f.isDirectory()) {
                    //获取文件对象
                    FileInfo info = getFolder(f, fileInfo);
                    //是否获取子文件列表
                    if (isChildren) {
                        List<FileInfo> list = getFileDirectoryTree(FileInfo.builder()
                                .filePath(fileInfo.getFilePath() + "/" + f.getName())
                                .build(), isFile, isChildren);
                        info.setChildrenFileList(list);
                    }
                    tree.add(0, info);

                } else {
                    //是否获取文件
                    if (isFile) {
                        tree.add(getFileInfo(f, fileInfo));
                    }
                }
            }
        }
        return tree;
    }

    /**
     * @param fileInfo 文件（文件夹）信息
     * @return: boolean
     * @Description: 删除文件或文件夹
     * @Author: HeYuanqing
     * @Date: 2022/11/22 14:48
     */
    public static boolean deleteFiles(FileInfo fileInfo) {


        File file = new File( fileInfo.getFilePath());
        if (!file.exists()) {
            throw new IllegalArgumentException("不存在该文件");
        }

        boolean result = true;
        if (file.isDirectory()) {
            try {
                FileUtils.deleteDirectory(file);
            } catch (IOException e) {
                result = false;
            }
        } else {
            result = file.delete();
        }
        return result;
    }


    /**
     * @param folderPath 新建文件地址
     * @return: boolean
     * @Description: 新建文件夹
     * @Author: HeYuanqing
     * @Date: 2024/1/3 10:14
     */
    public static boolean NewFolder(String folderPath) {
        File fold = new File(folderPath);
        if (fold.exists()) {
            return false;
        }
        fold.mkdirs();
        return true;
    }
    /**
     * @param f        查找文件
     * @param fileInfo 包含所在文件的文件（文件夹）
     * @return: com.hyq.ghfsystem.util.FileInfo
     * @Description: 获取文件属性列表
     * @Author: HeYuanqing
     * @Date: 2022/11/21 21:33
     */
    private static FileInfo getFileInfo(File f, FileInfo fileInfo) {
        FileInfo info = getFolder(f, fileInfo);
        info.setFileSize(f.length());

        info.setUpdateTime(new Date(f.lastModified()));
        info.setChildrenFileList(new ArrayList<>());
        String fileName = f.getName();
        String fileType = (fileName.substring(fileName.lastIndexOf("."))).substring(1);
        setDataType(info, fileType);

        return info;
    }

    /**
     * @param f        查找文件
     * @param fileInfo 包含所在文件的文件（文件夹）
     * @return: com.hyq.ghfsystem.util.FileInfo
     * @Description: 用户文件列表中文件的绝对路径
     * @Author: HeYuanqing
     * @Date: 2022/11/21 21:31
     */
    private static FileInfo getFolder(File f, FileInfo fileInfo) {
        FileInfo info = new FileInfo();
        info.setFileName(f.getName());
        info.setFilePath(IoUtil.convertLinuxPath(fileInfo.getFilePath() + "\\" + f.getName()));
        info.setAbsolutePath(IoUtil.convertLinuxPath(f.getAbsolutePath()));
        info.setFileType(fileInfo.getFileType());
        info.setUpdateTime(new Date(f.lastModified()));
        return info;
    }

    private static void setDataType(FileInfo fileInfo, String suffix) {
        switch (suffix) {
            case "xlsx":
                fileInfo.setFileType(FileType.excel);
                break;
            case "xls":
                fileInfo.setFileType(FileType.excel);
                break;

            case "pptx":
                fileInfo.setFileType(FileType.ppt);
                break;
            case "ppt":
                fileInfo.setFileType(FileType.ppt);
                break;
            case "docx":
                fileInfo.setFileType(FileType.word);
                break;
            case "doc":
                fileInfo.setFileType(FileType.word);
                break;
            case "csv":
                fileInfo.setFileType(FileType.csv);
                break;
            case "pdf":
                fileInfo.setFileType(FileType.pdf);
                break;
            case "zip":
                fileInfo.setFileType(FileType.zip);
                break;
            case "rar":
                fileInfo.setFileType(FileType.zip);
                break;
            case "txt":
                fileInfo.setFileType(FileType.txt);
                break;
            case "gif":
                fileInfo.setFileType(FileType.gif);
                break;
            case "shp":
                fileInfo.setFileType(FileType.shp);
                break;
            case "tif":
                fileInfo.setFileType(FileType.tif);
                break;
            case "mp3":
                fileInfo.setFileType(FileType.audio);
                break;
            case "wav":
                fileInfo.setFileType(FileType.audio);
                break;
            case "wma":
                fileInfo.setFileType(FileType.audio);
                break;
            case "mp4":
                fileInfo.setFileType(FileType.video);
                break;
            case "avi":
                fileInfo.setFileType(FileType.video);
            case "wmv":
                fileInfo.setFileType(FileType.video);
                break;
            case "mpg":
                fileInfo.setFileType(FileType.video);
                break;
            case "jpg":
                fileInfo.setFileType(FileType.image);
                break;
            case "png":
                fileInfo.setFileType(FileType.image);
                break;
            case "jpeg":
                fileInfo.setFileType(FileType.image);
                break;
            default:
                fileInfo.setFileType(FileType.unknown);
                break;
        }
    }

    public static List<Map> readFiles2EleTree(String dirPath) {
        List<Map> fileAndDirMap = new ArrayList<>(); // 存储目录信息

        // 建立当前目录中文件的File对象
        File curfile = new File(dirPath);

//        Map label = new HashMap();
//        label.put("label", curfile.getName());
//        fileAndDirMap.add(label);


        // 取得代表目录中所有文件的File对象数组
        File[] listFiles = curfile.listFiles();
        if (listFiles != null) {

            List<Map> children = new ArrayList<>(); // 存储文件夹下的文件信息

            for (File file : listFiles) {
                Map fileMap = new HashMap();
                fileMap.put("label",file.getName());
                if (file.isDirectory()) {

                    fileMap.put("children", readFiles2EleTree(file.getPath()));
                }
                fileAndDirMap.add(fileMap);
            }


        }


        return fileAndDirMap;
    }

    public static String ReadXMLFile(String path, String elementName) {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

        DocumentBuilder builder = null;
        try {

            builder = factory.newDocumentBuilder();
            Document document = builder.parse(path);
//            获取根节点
            Node root = document.getDocumentElement();
//            遍历子节点
            for (int i = 0; i < root.getChildNodes().getLength(); i++) {
                Node node = root.getChildNodes().item(i);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    // 处理元素节点
                    String nodeName = node.getNodeName();
                    String nodeValue = node.getTextContent();
                    System.out.println("Element Name: " + nodeName);
                    System.out.println("Element Value: " + nodeValue);
                }
            }

        } catch (ParserConfigurationException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (SAXException e) {
            throw new RuntimeException(e);
        }


        return null;
    }
    public static Map<String, Object> jsonObjectToMap(JSONObject jsonObject) {
        Map<String, Object> map = new HashMap<>();
        for (String key : jsonObject.keySet()) {
            Object value = jsonObject.get(key);
            if (value instanceof JSONObject) {
                map.put(key, jsonObjectToMap((JSONObject) value)); // 递归处理嵌套的JSONObject
            } else if (value instanceof JSONArray) {
                map.put(key, jsonArrayToList((JSONArray) value)); // 处理JSONArray，如果需要的话
            } else {
                map.put(key, value);
            }
        }
        return map;
    }

    // 可选：如果需要将JSONArray转换为List
    public static List<Object> jsonArrayToList(JSONArray jsonArray) {
        List<Object> list = new ArrayList<>();
        for (int i = 0; i < jsonArray.length(); i++) {
            Object value = jsonArray.get(i);
            if (value instanceof JSONObject) {
                list.add(jsonObjectToMap((JSONObject) value));
            } else if (value instanceof JSONArray) {
                list.add(jsonArrayToList((JSONArray) value));
            } else {
                list.add(value);
            }
        }
        return list;
    }
}
